package com.xxx.car.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xxx.car.constants.CouponStatus;
import com.xxx.car.constants.CouponType;
import com.xxx.car.entity.TbCoupon;
import com.xxx.car.entity.TbCouponPool;
import com.xxx.car.entity.TbCouponTpl;
import com.xxx.car.entity.vo.request.ReqCouponQuery;
import com.xxx.car.entity.vo.request.ReqCouponTpl;
import com.xxx.car.entity.vo.request.ReqCouponTplQueryForAdmin;
import com.xxx.car.entity.vo.response.RespCoupon;
import com.xxx.car.entity.vo.response.RespCouponTpl;
import com.xxx.car.mapper.TbCouponMapper;
import com.xxx.car.mapper.TbCouponPoolMapper;
import com.xxx.car.mapper.TbCouponTplMapper;
import com.xxx.car.service.CouponService;
import com.xxx.common.base.exception.BizException;
import com.xxx.common.util.IdWorker;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by wenjiexu on 2017/6/19.
 */
@Service
public class CouponServiceImpl implements CouponService {

    @Autowired
    private TbCouponMapper tbCouponMapper;
    @Autowired
    private TbCouponTplMapper tbCouponTplMapper;
    @Autowired
    private TbCouponPoolMapper tbCouponPoolMapper;
    @Autowired
    private IdWorker idWorker;

    @Override
    public void refreshStatus(Integer userId) {
        tbCouponMapper.updateForExpire(userId, CouponStatus.EXPIRE, CouponStatus.NOT_USE, new Date());
    }

    @Override
    public List<RespCoupon> query(ReqCouponQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        return tbCouponMapper.query(query).stream().map(e -> {
            RespCoupon respCoupon = new RespCoupon();
            BeanUtils.copyProperties(e, respCoupon);
            return  respCoupon;
        }).collect(Collectors.toList());
    }

    @Override
    public Integer queryUserCouponCount(Integer userId) {
        return tbCouponMapper.queryUserCouponCount(userId);
    }

    @Override
    public Page<RespCouponTpl> queryCouponTpl(ReqCouponTplQueryForAdmin reqCouponTplQueryForAdmin) {
        PageHelper.startPage(reqCouponTplQueryForAdmin.getPageNum(), reqCouponTplQueryForAdmin.getPageSize());
        Page<TbCouponTpl> couponTpls = (Page<TbCouponTpl>) tbCouponTplMapper.query();
        List<RespCouponTpl> respCouponTpls = couponTpls.stream().map(e -> {
            RespCouponTpl respCouponTpl = new RespCouponTpl();
            BeanUtils.copyProperties(e, respCouponTpl);
            return respCouponTpl;
        }).collect(Collectors.toList());

        Page<RespCouponTpl> page = new Page<>(reqCouponTplQueryForAdmin.getPageNum(), reqCouponTplQueryForAdmin.getPageSize());
        page.setTotal(couponTpls.getTotal());
        page.addAll(respCouponTpls);
        return page;
    }

    @Override
    @Transactional
    public void genCoupon(ReqCouponTpl reqCouponTpl) {
        Date now = new Date();

        TbCouponTpl couponTpl = new TbCouponTpl();
        if (reqCouponTpl.getCouponType() == CouponType.DISCOUNT) {
            String desc = reqCouponTpl.getDiscount().multiply(new BigDecimal(10)).toString() + "折";
            couponTpl.setCouponName(desc);
            couponTpl.setCouponDetail(desc);
        }
        if (reqCouponTpl.getCouponType() == CouponType.SUB_AMT) {
            String desc = "";
            if (reqCouponTpl.getMinLimit() != null) {
                desc += "满" + reqCouponTpl.getMinLimit()/100;
            }
            if (reqCouponTpl.getSubAmt() != null) {
                desc += "减" + reqCouponTpl.getSubAmt()/100;
            }
            couponTpl.setCouponName(desc);
            couponTpl.setCouponDetail(desc);
        }
        couponTpl.setCouponType(reqCouponTpl.getCouponType());
        couponTpl.setDiscount(reqCouponTpl.getDiscount());
        couponTpl.setSubAmt(reqCouponTpl.getSubAmt());
        couponTpl.setMinLimit(reqCouponTpl.getMinLimit());
        couponTpl.setCreateTime(now);
        couponTpl.setUpdateTime(now);
        couponTpl.setExpireTime(reqCouponTpl.getExpireTime());
        couponTpl.setGenNum(reqCouponTpl.getGenNum());

        tbCouponTplMapper.insertSelective(couponTpl);

        if (reqCouponTpl.getGenNum() > 0) {
            List<TbCouponPool> pools = new ArrayList<>();
            for (int i = 0; i < reqCouponTpl.getGenNum(); i++) {
                TbCouponPool e = new TbCouponPool();
                e.setTplId(couponTpl.getId());
                String tickId = String.valueOf(idWorker.nextId());
                e.setCouponTicket(tickId.substring(tickId.length() - 8, tickId.length()));
                e.setCreateTime(now);
                pools.add(e);
            }
            tbCouponPoolMapper.batchInsert(pools);
        }
    }

    @Override
    @Transactional
    public void exchangeCoupon(Integer userId, String couponTicket) {
        TbCouponPool coupon = tbCouponPoolMapper.selectByPrimaryKeyForUpdate(couponTicket);
        if (coupon == null) {
            throw new BizException("优惠券不存在");
        }
        if (coupon.getObtainUser() != null) {
            throw new BizException("优惠券已使用");
        }
        TbCouponTpl tpl = tbCouponTplMapper.selectByPrimaryKey(coupon.getTplId());
        if (tpl == null) {
            throw new BizException("优惠券模板不存在");
        }

        Date now = new Date();

        coupon.setObtainTime(now);
        coupon.setObtainUser(userId);
        tbCouponPoolMapper.updateByPrimaryKeySelective(coupon);

        TbCoupon userCoupon = new TbCoupon();
        userCoupon.setUserId(userId);
        userCoupon.setCouponTicket(couponTicket);
        userCoupon.setCouponName(tpl.getCouponName());
        userCoupon.setCouponDetail(tpl.getCouponDetail());
        userCoupon.setCouponType(tpl.getCouponType());
        userCoupon.setDiscount(tpl.getDiscount());
        userCoupon.setSubAmt(tpl.getSubAmt());
        userCoupon.setMinLimit(tpl.getMinLimit());
        userCoupon.setStatus(CouponStatus.NOT_USE);
        userCoupon.setExpireTime(tpl.getExpireTime());
        userCoupon.setCreateTime(now);
        userCoupon.setUpdateTime(now);

        tbCouponMapper.insertSelective(userCoupon);
    }

    @Override
    public void useCoupon(Integer userId, Integer couponId) {
        TbCoupon tbCoupon = tbCouponMapper.selectByPrimaryKey(couponId);
        if (!tbCoupon.getUserId().equals(userId)) {
            throw new BizException("优惠券异常");
        }
        if (!tbCoupon.getStatus().equals(CouponStatus.NOT_USE)) {
            throw new BizException("优惠券已使用");
        }
        Date now = new Date();
        if (tbCoupon.getExpireTime() != null && tbCoupon.getExpireTime().before(now)) {
            throw new BizException("优惠券已过期");
        }
        TbCoupon updateParam = new TbCoupon();
        updateParam.setId(couponId);
        updateParam.setStatus(CouponStatus.HAS_USE);
        updateParam.setUserTime(now);
        updateParam.setUpdateTime(now);
        tbCouponMapper.updateByPrimaryKeySelective(updateParam);
    }
}
